package org.example.zk_util

import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.http.content.*
import io.ktor.server.netty.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
import io.ktor.websocket.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.ClosedReceiveChannelException
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import java.io.File
import java.time.Duration
import kotlin.time.toKotlinDuration

class WebServer {
    private var server: EmbeddedServer<NettyApplicationEngine, NettyApplicationEngine.Configuration>? = null
    private lateinit var zkClient: ZkClient
    private val json = Json { prettyPrint = true }

    fun start(port: Int, zkConnectString: String) {
        // 初始化 ZooKeeper 客户端
        zkClient = ZkClient()
        zkClient.connect(zkConnectString)

        server = embeddedServer(Netty, port = port) {
            install(WebSockets) {
                pingPeriod = Duration.ofSeconds(15).toKotlinDuration()
                timeout = Duration.ofSeconds(15).toKotlinDuration()
                maxFrameSize = Long.MAX_VALUE
                masking = false
            }
            configureServer()
        }
        server?.start(wait = false)
        println("Web server started on port $port  http://localhost:$port/")
    }

    fun stop() {
        server?.stop(1000, 5000)
        zkClient.close()
        println("Web server stopped")
    }

    private fun Application.configureServer() {
        routing {
            // 静态资源路由，用于提供前端文件
            staticResources("/", "static")

            // API路由
            get("/api/zk/tree") {
                val tree = zkClient.traverseNode("/")
                call.respondText(json.encodeToString(tree))
            }

            get("/api/zk/node") {
                val path = call.parameters["path"] ?: "/"
                val data = zkClient.getNodeData(path)
                call.respondText(data)
            }

            post("/api/zk/node") {
                val path = call.parameters["path"] ?: return@post call.respondText("Path is required")
                val data = call.receiveText()
                val success = zkClient.setNodeData(path, data)
                call.respondText(if (success) "OK" else "Failed")
            }

            post("/api/zk/node/create") {
                val path = call.parameters["path"] ?: return@post call.respondText("Path is required")
                val data = call.receiveText()
                val success = zkClient.createNode(path, data)
                call.respondText(if (success) "OK" else "Failed")
            }

            delete("/api/zk/node") {
                val path = call.parameters["path"] ?: return@delete call.respondText("Path is required")
                val success = zkClient.deleteNode(path)
                call.respondText(if (success) "OK" else "Failed")
            }

            // WebSocket 用于实时更新
            webSocket("/ws/zk") {
                // 创建一个协程作用域，与WebSocket会话生命周期绑定
                val webSocketScope = CoroutineScope(Dispatchers.IO)
                try {
                    // 监听根节点的子节点变化
                    zkClient.watchChildren("/") { path, children ->
                        val update = mapOf(
                            "type" to "children_changed",
                            "path" to path,
                            "children" to children
                        )
                        webSocketScope.launch {
                            send(Frame.Text(json.encodeToString(update)))
                        }
                    }

                    // 处理客户端消息
                    for (frame in incoming) {
                        frame as? Frame.Text ?: continue
                        val message = frame.readText()
                        val request = json.decodeFromString<Map<String, String>>(message)
                        
                        when (request["action"]) {
                            "watch_node" -> {
                                val path = request["path"] ?: continue
                                zkClient.watchNode(path) { nodePath, data ->
                                    val update = mapOf(
                                        "type" to "node_data_changed",
                                        "path" to nodePath,
                                        "data" to data
                                    )
                                    webSocketScope.launch {
                                        send(Frame.Text(json.encodeToString(update)))
                                    }
                                }
                            }
                        }
                    }
                } catch (e: ClosedReceiveChannelException) {
                    // 连接关闭
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }

            // 默认路由返回主页面
            get("/") {
                call.resolveResource("static/index.html")?.let {
                    call.respondFile(File("src/main/resources/static/index.html"))
                } ?: call.respondText("Welcome to integrated web application!")
            }
        }
    }
}
